package org.jvm.classfile.attributeinfo;

import org.jvm.classfile.*;

/**
 * author : wangsixiang02
 * date : 2023/1/8
 * desc :
 */
public class AttributeInfoBuilder {

    /**
     * 属性的开头会有一个字符串标识属性类型
     */
    public static final String ATTRIBUTE_Code = "Code";
    public static final String ATTRIBUTE_ConstantValue = "ConstantValue";
    public static final String ATTRIBUTE_Deprecated = "Deprecated";
    public static final String ATTRIBUTE_Exceptions = "Exceptions";
    public static final String ATTRIBUTE_SourceFile = "SourceFile";
    public static final String ATTRIBUTE_Synthetic = "Synthetic";
    public static final String ATTRIBUTE_LineNumberTable = "LineNumberTable";

    /**
     * 批量读取属性表
     *
     * @param classReader
     * @param constantPool
     * @return
     */
    public static AttributeInfo[] newAttributeInfos(ClassReader classReader, ConstantPool constantPool) {
        int attributeCount = classReader.readUint16();
        AttributeInfo[] res = new AttributeInfo[attributeCount];
        for (int i = 0; i < attributeCount; i++) {
            res[i] = newAttributeInfo(classReader, constantPool);
        }
        return res;
    }

    /**
     * 根据头字节的tag判断常量类型，初始化常量
     *
     * @param classReader
     * @param constantPool
     * @return
     */
    private static AttributeInfo newAttributeInfo(ClassReader classReader, ConstantPool constantPool) {
        AttributeInfo res;
        int attributeNameIndex = classReader.readUint16();
        String attributeName = constantPool.getUtf8(attributeNameIndex);
        //每个属性中都会有属性字节长度
        int attributeLength = classReader.readUint32();
        switch (attributeName) {
            case ATTRIBUTE_Code:
                res = new CodeAttribute(constantPool);
                break;
            case ATTRIBUTE_ConstantValue:
                res = new ConstantValueAttribute();
                break;
            case ATTRIBUTE_Deprecated:
                res = new DeprecatedAttribute();
                break;
            case ATTRIBUTE_Exceptions:
                res = new ExceptionsAttribute();
                break;
            case ATTRIBUTE_SourceFile:
                res = new SourceFileAttribute(constantPool);
                break;
            case ATTRIBUTE_Synthetic:
                res = new SourceFileAttribute(constantPool);
                break;
            case ATTRIBUTE_LineNumberTable:
                res = new LineNumberTableAttribute();
                break;
            //对于不支持的属性类型，依然要读出来，目的是移动classReader的指针
            default:
                res = new UnparsedAttribute(attributeName);
        }
        res.readInfo(classReader, attributeLength);
        return res;
    }
}
